﻿using FastCloud.Base;
using FastCloud.Base.Config;
using FastCloud.Base.Desgin;
using FastCloud.DMP.DB;
using FastCloud.DMP.Entity;
using FastIOC.Attribute;
using FastORM.Entity;
using FastUtil.Convert;
using FastUtil.Data;
using FastUtil.Extra;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml;

namespace FastCloud.Controllers.DMP
{
    [Route("frame/dmp/table")]
    public class TableController : BaseController
    {
        [AutoWired]
        private DB_Project DB_Project;
        [AutoWired]
        private DB_Table DB_Table;
        [AutoWired]
        private DB_Column DB_Column;
        [AutoWired]
        private DB_DMP DB_DMP;


        [Route("list")]
        public IActionResult List()
        {
            return View("~/Views/DMP/Table/Table_List.cshtml");
        }
        [Route("add")]
        public IActionResult Add()
        {
            return View("~/Views/DMP/Table/Table_Add.cshtml");
        }
        [Route("edit")]
        public IActionResult Edit()
        {
            return View("~/Views/DMP/Table/Table_Edit.cshtml");
        }
        [Route("code")]
        public IActionResult Code()
        {
            return View("~/Views/DMP/Table/CodeGenerateSetting.cshtml");
        }
        [Route("codepreview")]
        public IActionResult CodePreview()
        {
            return View("~/Views/DMP/Table/CodePreview.cshtml");
        }

        [Route("oplist"), HttpPost]
        public IActionResult OpList()
        {
            string TableName = ValueConvert.ConvertToString(GetFormParam("TableName"));
            string TablePhysicalName = ValueConvert.ConvertToString(GetFormParam("TablePhysicalName"));
            string TableCode = ValueConvert.ConvertToString(GetFormParam("TableCode"));
            string ProjectGuid = ValueConvert.ConvertToString(GetFormParam("ProjectGuid"));
            bool SearchInAll = ValueConvert.ConvertToBoolean(GetFormParam("SearchInAll"));
            string sql = "1=1";
            List<ParamEntity> ParamList = new List<ParamEntity>();
            if (!string.IsNullOrEmpty(TableName))
            {
                sql += " and TableName like @TableName";
                ParamList.Add(new ParamEntity() { ParamName = "TableName", ParamValue = "%" + TableName + "%" });
            }
            if (!string.IsNullOrEmpty(TablePhysicalName))
            {
                sql += " and TablePhysicalName like @TablePhysicalName";
                ParamList.Add(new ParamEntity() { ParamName = "TablePhysicalName", ParamValue = "%" + TablePhysicalName + "%" });
            }
            if (!string.IsNullOrEmpty(TableCode))
            {
                sql += " and TableCode like @TableCode";
                ParamList.Add(new ParamEntity() { ParamName = "TableCode", ParamValue = "%" + TableCode + "%" });
            }
            if (!SearchInAll)
            {
                if (!string.IsNullOrEmpty(ProjectGuid) && ProjectGuid != "Top")
                {
                    sql += " and ProjectGuid=@ProjectGuid";
                    ParamList.Add(new ParamEntity() { ParamName = "ProjectGuid", ParamValue = ProjectGuid });
                }
            }
            return Result.OK(DB_Table.SelectPage("*", sql, "SortNum desc", ParamList));
        }

        [Route("opinsert"), HttpPost]
        public IActionResult OpInsert(Frame_Table Entity)
        {
            if (!DB_Table.ExistTable(Entity.TablePhysicalName))
            {
                Entity.TableGuid = GenerateUtil.GenerateUnitGuid();
                DB_DMP.InitTableDefaultStruct(Entity.TableGuid, Entity.TablePhysicalName);
                DB_Table.Insert(Entity);
                return Result.OK();
            }
            else
            {
                return Result.Error("数据表已存在");
            }

        }

        [Route("opupdate"), HttpPost]
        public IActionResult OpUpdate(Frame_Table Entity)
        {
            DB_Table.UpdateByID(Entity);
            return Result.OK();
        }

        [Route("opdetail"), HttpPost]
        public IActionResult OpDetail()
        {
            string TableGuid = ValueConvert.ConvertToString(GetFormParam("TableGuid"));
            return Result.OK(DB_Table.SelectOne(TableGuid));
        }

        [Route("opbatchdelete"), HttpPost]
        public IActionResult OpBatchDelete()
        {
            string KeyID = ValueConvert.ConvertToString(GetFormParam("KeyID"));
            List<string> KeyIDList = KeyID.TrimEnd(';').Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            DB_Table.DeleteBatch(KeyIDList);
            foreach (string TableGuid in KeyIDList)
            {
                DB_Column.DeleteByFiled("TableGuid", TableGuid);
            }
            return Result.OK();
        }

        [Route("exportxml"), HttpGet]
        public ContentResult ExportXML()
        {
            ContentResult result = new ContentResult();
            string KeyID = ValueConvert.ConvertToString(GetRequestParam("KeyID"));
            List<string> KeyGuidList = KeyID.TrimEnd(';').Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            XmlDocument Doc = new XmlDocument();
            //创建根节点    
            XmlNode Root = Doc.CreateElement("ExportFile");
            ExportFileInfo FileInfo = new ExportFileInfo("DMPStruct");
            XmlNode FileInfoNode = Doc.CreateElement("FileInfo");
            FileInfoNode.InnerXml = StructConvert.ConvertEnity2InnerXml(FileInfo);
            Root.AppendChild(FileInfoNode);
            List<Frame_Project> ProjectEntityList = new List<Frame_Project>();
            foreach (string KeyGuid in KeyGuidList)
            {
                Frame_Table Entity = DB_Table.SelectOne(KeyGuid);
                List<Frame_Column> ColumnEntityList = DB_Column.SelectColumnByTableGuid(Entity.TableGuid);
                if (KeyGuidList.IndexOf(KeyGuid) == 0)
                {
                    //导出时肯定是同项目的，所以项目信息只要获取一次
                    ProjectEntityList.AddRange(DB_Project.SelectAllDeepByProjectGuid(Entity.ProjectGuid));
                }
                XmlNode Table = Doc.CreateElement("Table");
                XmlNode TableDetail = Doc.CreateElement("TableDetail");
                TableDetail.InnerXml = StructConvert.ConvertEnity2InnerXml(Entity);
                Table.AppendChild(TableDetail);
                XmlNode ColumnList = Doc.CreateElement("ColumnList");
                foreach (Frame_Column Item in ColumnEntityList)
                {
                    XmlNode Column = Doc.CreateElement("Column");
                    Column.InnerXml = StructConvert.ConvertEnity2InnerXml(Item);
                    ColumnList.AppendChild(Column);
                }
                Table.AppendChild(ColumnList);
                Root.AppendChild(Table);
            }
            foreach (Frame_Project Item in ProjectEntityList)
            {
                XmlNode Project = Doc.CreateElement("Project");
                Project.InnerXml = StructConvert.ConvertEnity2InnerXml(Item);
                Root.AppendChild(Project);
            }


            Doc.AppendChild(Root);
            result.Content = StructConvert.ConvertXml2String(Doc);
            result.ContentType = "text/xml";
            return result;
        }

        [Route("importxml"), HttpPost]
        public IActionResult ImportXML()
        {
            IFormFileCollection FileList = Request.Form.Files;
            if (FileList != null && FileList.Count > 0)
            {
                FormFile file = (FormFile)FileList[0];
                //暂存文件
                string FilePath = CloudUtil.GetAttachUploadPath("DMPStructImport") + "/" + GenerateUtil.GenerateUnitGuid() + System.IO.Path.GetExtension(file.FileName);
                using (FileStream fstream = new FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    file.CopyTo(fstream);
                }
                //解析
                StreamReader Reader = new StreamReader(FilePath, System.Text.Encoding.UTF8);
                string StramReader = Reader.ReadToEnd().Trim();
                XmlDocument Doc = new XmlDocument();
                Doc.LoadXml(StramReader);
                XmlNode FileInfoNode = Doc.SelectSingleNode("/ExportFile/FileInfo");
                ExportFileInfo FileInfo = StructConvert.ConvertXMLNode2Entity<ExportFileInfo>(FileInfoNode);
                if (FileInfo.FileType == "DMPStruct")
                {
                    XmlNodeList TableNodeList = Doc.SelectNodes("/ExportFile/Table");
                    foreach (XmlNode TableNode in TableNodeList)
                    {
                        XmlNode TableDetailNode = TableNode.SelectSingleNode("TableDetail");
                        Frame_Table Table = StructConvert.ConvertXMLNode2Entity<Frame_Table>(TableDetailNode);
                        if (DB_Table.ExistTable(Table.TablePhysicalName))
                        {
                            DB_Table.UpdateByFieldName(Table, "TablePhysicalName");
                        }
                        else
                        {
                            DB_Table.Insert(Table);
                        }
                        //获取导入前数据库所有列信息
                        List<string> DBPhysicalColumnNameList = DB_Column.SelectColumnByTableGuid(Table.TableGuid).Select(o => o.PhysicalColumnName).ToList();
                        List<string> ImportPhysicalColumnNameList = new List<string>();
                        XmlNodeList ColumnNodeList = TableNode.SelectNodes("ColumnList/Column");
                        foreach (XmlNode ColumnNode in ColumnNodeList)
                        {
                            Frame_Column Column = StructConvert.ConvertXMLNode2Entity<Frame_Column>(ColumnNode);
                            ImportPhysicalColumnNameList.Add(Column.PhysicalColumnName);
                            if (DB_Column.ExistColumn(Column.TableGuid,Column.PhysicalColumnName))
                            {
                                DB_Column.UpdateByFieldName(Column, "PhysicalColumnName");
                            }
                            else
                            {
                                DB_Column.Insert(Column);
                            }
                        }

                        //删除原数据库有，导入没有的列
                        DBPhysicalColumnNameList = DBPhysicalColumnNameList.Where(a => !ImportPhysicalColumnNameList.Contains(a)).ToList();
                        foreach (string item in DBPhysicalColumnNameList)
                        {
                            DB_Column.DeleteByPhysicalColumnName(item);
                        }
                    }
                    XmlNodeList ProjectNodeList = Doc.SelectNodes("/ExportFile/Project");
                    foreach (XmlNode ProjectNode in ProjectNodeList)
                    {
                        Frame_Project Project = StructConvert.ConvertXMLNode2Entity<Frame_Project>(ProjectNode);
                        DB_Project.DeleteByID(Project.ProjectGuid);
                        DB_Project.Insert(Project);
                    }
                }
                else
                {
                    return Result.Error("XML文件类型不正确");
                }
            }
            else
            {
                return Result.Error("未选择文件");
            }
            return Result.OK();
        }

        [Route("generateTemplateCode"), HttpPost]
        public IActionResult GenerateTemplateCode()
        {
            Hashtable result = new Hashtable();
            string TableGuidList = ValueConvert.ConvertToString(GetFormParam("TableGuidList"));
            string Prefix = ValueConvert.ConvertToString(GetFormParam("Prefix"));
            string NameSpace = ValueConvert.ConvertToString(GetFormParam("NameSpace"));
            string ClassRoute = ValueConvert.ConvertToString(GetFormParam("ClassRoute"));
            string PageRoute = ValueConvert.ConvertToString(GetFormParam("PageRoute"));
            string FileID = "CodeGenerate" + GenerateUtil.GenerateUnitGuid();
            string[] PageColumnFilter = new string[] { "RowGuid", "UserGuid", "UserName", "OUGuid", "OUName", "PVIGuid", "AddDate", "SortNum" };
            Dictionary<string, object> CodeDic = new Dictionary<string, object>();
            foreach (string TableGuid in TableGuidList.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList())
            {
                Frame_Table TableEntity = DB_Table.SelectOne(TableGuid);
                List<Frame_Column> ColumnList = DB_Column.SelectColumnByTableGuid(TableGuid);
                List<Frame_Column> PageColumnList = ColumnList.Where(a => !PageColumnFilter.Contains(a.PhysicalColumnName)).ToList();
                string ClearPrefixName = TableEntity.TablePhysicalName;
                if (!string.IsNullOrEmpty(Prefix))
                {
                    ClearPrefixName = TableEntity.TablePhysicalName.Replace(Prefix, string.Empty);
                }
                CodeDic.Clear();
                CodeDic.Add("NameSpace", NameSpace);
                CodeDic.Add("ClassRoute", ClassRoute);
                CodeDic.Add("PageRoute", PageRoute);
                CodeDic.Add("TablePhysicalName", TableEntity.TablePhysicalName);
                CodeDic.Add("TableName", TableEntity.TableName);
                CodeDic.Add("TablePhysicalNameLowCase", TableEntity.TablePhysicalName.ToLower());
                CodeDic.Add("ClearPrefixName", ClearPrefixName);
                CodeDic.Add("ColumnList", ColumnList);
                CodeDic.Add("PageColumnList", PageColumnList);
                TemplateUtil.GeneratemeplateFile(FileID, TableEntity.TablePhysicalName, "Code_EntityTemplate.vm", TableEntity.TablePhysicalName + ".cs", CodeDic);
                TemplateUtil.GeneratemeplateFile(FileID, TableEntity.TablePhysicalName, "Code_DBTemplate.vm", "DB_" + ClearPrefixName + ".cs", CodeDic);
                TemplateUtil.GeneratemeplateFile(FileID, TableEntity.TablePhysicalName, "Code_ControllerTemplate.vm", ClearPrefixName + "Controller" + ".cs", CodeDic);
                TemplateUtil.GeneratemeplateFile(FileID, TableEntity.TablePhysicalName, "Page_ListTemplate.vm", ClearPrefixName + "_List" + ".cshtml", CodeDic);
                TemplateUtil.GeneratemeplateFile(FileID, TableEntity.TablePhysicalName, "Page_AddTemplate.vm", ClearPrefixName + "_Add" + ".cshtml", CodeDic);
                TemplateUtil.GeneratemeplateFile(FileID, TableEntity.TablePhysicalName, "Page_EditTemplate.vm", ClearPrefixName + "_Edit" + ".cshtml", CodeDic);
            }
            string CodePath = CloudUtil.GetContentStaticFilePath() + TemplateUtil.CodeTempPath + "/" + FileID;
            ZipUtil.CompressDirectory(CodePath, CloudUtil.GetContentStaticFilePath() + TemplateUtil.CodeTempPath + "/" + FileID + ".zip", 5, true);
            result.Add("GenerateCodeDownLoadUrl", CloudUtil.GetRootPath() + "StaticFile/" + TemplateUtil.CodeTempPath + "/" + FileID + ".zip");
            return Result.OK(result);
        }
    }
}
